package com.randi.common.utils.excel;

import com.randi.common.annotation.Excel;
import com.randi.common.utils.StringUtils;
import org.apache.poi.ss.usermodel.*;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ziye
 */
public class ExcelStyleUtil {

    private static final String FONT_NAME = "Arial";

    private static final Short FONT_TITLE_HEIGHT = 16;

    private static final Boolean FONT_TITLE_BOLD = true;

    private static final Short FONT_DATA_HEIGHT = 10;

    private static final HorizontalAlignment HORIZONTAL_ALIGNMENT = HorizontalAlignment.CENTER;

    private static final VerticalAlignment VERTICAL_ALIGNMENT = VerticalAlignment.CENTER;

    private static final BorderStyle BORDER_STYLE = BorderStyle.THIN;

    private static final Short BORDER_COLOR = IndexedColors.GREY_50_PERCENT.getIndex();

    /**
     * 创建标题样式
     *
     * @param wb 工作薄对象
     * @return 样式
     */
    public static CellStyle createTitleStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HORIZONTAL_ALIGNMENT);
        style.setVerticalAlignment(VERTICAL_ALIGNMENT);
        Font titleFont = wb.createFont();
        titleFont.setFontName(FONT_NAME);
        titleFont.setFontHeightInPoints(FONT_TITLE_HEIGHT);
        titleFont.setBold(FONT_TITLE_BOLD);
        style.setFont(titleFont);
        DataFormat dataFormat = wb.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));
        return style;
    }

    /**
     * 创建数据样式
     *
     * @param wb 工作薄对象
     * @return 样式
     */
    public static CellStyle createDataStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderTop(BORDER_STYLE);
        style.setBorderLeft(BORDER_STYLE);
        style.setBorderBottom(BORDER_STYLE);
        style.setBorderRight(BORDER_STYLE);
        style.setTopBorderColor(BORDER_COLOR);
        style.setLeftBorderColor(BORDER_COLOR);
        style.setBottomBorderColor(BORDER_COLOR);
        style.setRightBorderColor(BORDER_COLOR);
        Font dataFont = wb.createFont();
        dataFont.setFontName(FONT_NAME);
        dataFont.setFontHeightInPoints(FONT_DATA_HEIGHT);
        style.setFont(dataFont);
        return style;
    }

    /**
     * 创建合计样式
     *
     * @param wb 工作薄对象
     * @return 合计样式
     */
    public static CellStyle createTotalStyle(Workbook wb) {
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HORIZONTAL_ALIGNMENT);
        style.setVerticalAlignment(VERTICAL_ALIGNMENT);
        Font totalFont = wb.createFont();
        totalFont.setFontName(FONT_NAME);
        totalFont.setFontHeightInPoints(FONT_DATA_HEIGHT);
        style.setFont(totalFont);
        return style;
    }

    /**
     * 根据Excel注解创建表格头样式
     *
     * @param wb 工作薄对象
     * @return 自定义样式列表
     */
    public static Map<String, CellStyle> annotationHeaderStyles(Workbook wb, List<Object[]> fields, Map<String, CellStyle> styles) {
        Map<String, CellStyle> headerStyles = new HashMap<>(fields.size());
        fields.forEach(os -> annotationHeaderStyle(wb, (Field) os[0], styles, (Excel) os[1]));
        return headerStyles;
    }

    private static void annotationHeaderStyle(Workbook wb, Field field, Map<String, CellStyle> styles, Excel excel) {
        String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
        if (!styles.containsKey(key)) {
            CellStyle style = wb.createCellStyle();
            style.cloneStyleFrom(styles.get("data"));
            style.setAlignment(HORIZONTAL_ALIGNMENT);
            style.setVerticalAlignment(VERTICAL_ALIGNMENT);
            style.setFillForegroundColor(excel.headerBackgroundColor().index);
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

            Font headerFont = wb.createFont();
            headerFont.setFontName(FONT_NAME);
            headerFont.setFontHeightInPoints(FONT_DATA_HEIGHT);
            headerFont.setBold(true);
            headerFont.setColor(excel.headerColor().index);
            style.setFont(headerFont);

            // 设置表格头单元格文本形式
            DataFormat dataFormat = wb.createDataFormat();
            style.setDataFormat(dataFormat.getFormat("@"));
            styles.put(key, style);
        }

    }

    /**
     * 根据Excel注解创建表格列样式
     *
     * @param wb 工作薄对象
     * @return 自定义样式列表
     */
    public static Map<String, CellStyle> annotationDataStyles(Workbook wb, List<Object[]> fields, Map<String, CellStyle> styles ) {
        Map<String, CellStyle> dataStyles = new HashMap<>(fields.size());
        fields.forEach(os -> annotationDataStyles(wb, (Field) os[0], styles, (Excel) os[1]));
        return dataStyles;
    }

    /**
     * 根据Excel注解创建表格列样式
     *
     * @param styles 自定义样式列表
     * @param field  属性列信息
     * @param excel  注解信息
     */
    private static void annotationDataStyles(Workbook wb, Field field, Map<String, CellStyle> styles, Excel excel) {
        String key = StringUtils.format("data_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType());
        if (!styles.containsKey(key)) {
            CellStyle style = wb.createCellStyle();
            style.setAlignment(excel.align());
            style.setVerticalAlignment(VerticalAlignment.CENTER);

            style.setBorderTop(BORDER_STYLE);
            style.setBorderBottom(BORDER_STYLE);
            style.setBorderLeft(BORDER_STYLE);
            style.setBorderRight(BORDER_STYLE);
            style.setTopBorderColor(BORDER_COLOR);
            style.setBottomBorderColor(BORDER_COLOR);
            style.setLeftBorderColor(BORDER_COLOR);
            style.setRightBorderColor(BORDER_COLOR);

            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            style.setFillForegroundColor(excel.backgroundColor().getIndex());
            Font dataFont = wb.createFont();
            dataFont.setFontName(FONT_NAME);
            dataFont.setFontHeightInPoints(FONT_DATA_HEIGHT);
            dataFont.setColor(excel.color().index);
            style.setFont(dataFont);
            if (Excel.ColumnType.TEXT == excel.cellType()) {
                DataFormat dataFormat = wb.createDataFormat();
                style.setDataFormat(dataFormat.getFormat("@"));
            }
            styles.put(key, style);
        }
    }

}
